package org.jdsm.flow.core.users.impl.jpa.dao;

import org.jdsm.flow.core.users.IRole;
import org.jdsm.flow.core.users.impl.jpa.Role;
import org.jdsm.flow.core.utils.impl.jpa.GenericDao;
import org.jdsm.flow.core.utils.impl.jpa.PersistenceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.TypedQuery;
import java.util.*;




/**
 * User: mikom
 * Date: 3/14/13
 * Time: 5:11 PM
 */
public class RoleDAO extends GenericDao<Role, Long> {
    private static final Logger log = LoggerFactory.getLogger(RoleDAO.class);

    public IRole load(IRole<Long> role) {
        IRole result = null;
        if (role == null) {
            log.warn("role can't be null");
            return null;
        }
        if (role.getId() != null) {
            result = find(role.getId());
        }
        if (result == null && role.getName() != null) {
            result = findByName(role.getName());
        }
        log.debug("found role: {}", result);
        return result;
    }

    public Collection<Role> load(Collection<Long> entityIds){
        List<Role> result = PersistenceUtils.loadEntitiesByIds(getEntityManager(), Role.class, entityIds);
        return new LinkedHashSet<Role>(result);
    }


    public Collection<IRole> load(int maxResult, int startResult, boolean isSort, String field) {
        List<Role> result = PersistenceUtils.
                loadedByCriteria(getEntityManager(), Role.class, maxResult, startResult, isSort, field);
        return new LinkedHashSet<IRole>(result);
    }

    public IRole findByName(String name) {
        log.debug("find role by name: {}", name);
        if (name == null) {
            log.warn("role  name is null");
            return null;
        }
        try {
            return getEntityManager().createNamedQuery("role.findRoleByName", Role.class)
                    .setParameter("roleName", name).getSingleResult();
        } catch (NoResultException e) {
            log.warn("could not found role by name:{}", name);
            log.debug("trace: ", e);
            return null;
        } catch (NonUniqueResultException e) {
            log.warn("non unique role by name: {}", name);
            log.debug("trace: ", e);
            return null;
        }
    }

    public int count() {
        return PersistenceUtils.count(getEntityManager(), Role.class).intValue();
    }

    public Collection<IRole> findAllowed(Long permission) {
        if (permission == null) {
            log.warn("permission can't be null");
            return Collections.emptySet();
        }
        try {
            TypedQuery<Role> tq = getEntityManager().createNamedQuery("role.findAllowRoles", Role.class)
                    .setParameter("rolePermission", permission);
            List<Role> rs = tq.getResultList();

            if (log.isDebugEnabled()) {
                for (IRole role : rs) {
                    log.debug("role in result: {}", role);
                }
            }
            return new HashSet<IRole>(rs);
        } catch (NoResultException e) {
            log.warn("could not found allowed groups by permission:{}", permission);
            log.debug("trace: ", e);
            return Collections.emptySet();
        }
    }

    public IRole newInstance() {
        return new Role();
    }

    public IRole newInstance(String roleName, Long permission) {
        Role role = (Role) newInstance();
        role.setName(roleName);
        role.setPermission(permission);
        return role;
    }
}
